﻿/*
  planner.h - buffers movement commands and manages the acceleration profile plan
  Part of Grbl

  Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
  Copyright (c) 2009-2011 Simen Svale Skogsrud

  Grbl is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Grbl is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef planner_h
#define planner_h


// The number of linear motions that can be in the plan at any give time
#ifndef BLOCK_BUFFER_SIZE
  #ifdef USE_LINE_NUMBERS
    #define BLOCK_BUFFER_SIZE 15
  #else
    #define BLOCK_BUFFER_SIZE 16
  #endif
#endif

// Returned status message from planner.
#define PLAN_OK true
#define PLAN_EMPTY_BLOCK false

// Define planner data condition flags. Used to denote running conditions of a block.
#define PL_COND_FLAG_RAPID_MOTION      bit(0) // 表示G代码块是否为快速移动
#define PL_COND_FLAG_SYSTEM_MOTION     bit(1) // 回零等系统运动
#define PL_COND_FLAG_NO_FEED_OVERRIDE  bit(2) // G代码块是否禁止进给速率覆盖
#define PL_COND_FLAG_INVERSE_TIME      bit(3) // 逆时间模式下，进给速率是以每单位时间移动的单位数量来指定的，而不是以每分钟移动的距离来指定。
#define PL_COND_FLAG_SPINDLE_CW        bit(4)
#define PL_COND_FLAG_SPINDLE_CCW       bit(5)
#define PL_COND_FLAG_COOLANT_FLOOD     bit(6)
#define PL_COND_FLAG_COOLANT_MIST      bit(7)
#define PL_COND_MOTION_MASK    (PL_COND_FLAG_RAPID_MOTION|PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE)
#define PL_COND_SPINDLE_MASK   (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW)
#define PL_COND_ACCESSORY_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW|PL_COND_FLAG_COOLANT_FLOOD|PL_COND_FLAG_COOLANT_MIST)


// 运动规划块数据
typedef struct {
  // 由步进控制算法使用的块数据。
  uint32_t steps[N_AXIS];    // 线段每个轴的步进增量
  uint32_t step_event_count; // 完成此块所需的最大步数（移动步数最多的轴步数）
  uint8_t direction_bits;    // 此块的移动方向位集 (refers to *_DIRECTION_BIT in config.h)

  uint8_t condition;      // 从 pl_line_data 复制标志位，例如系统移动、快速移动等。

  // 运动规划器用来管理加速的字段。其中一些值可以由步进模块在执行特殊运动情况时更新，以进行重新规划。
  float entry_speed_sqr;     // 块连接处的当前计划入口速度，单位为（mm/min）^2。
  float max_entry_speed_sqr; // 基于转角限制和相邻名义速度的最小值以及覆盖的最大允许入口速度，单位为（mm/min）^2。
  float acceleration;        // 根据轴限制调整的线加速度，单位为（mm/min^2）,此值不改变。
  float millimeters;         // 此块实际要执行的剩余距离，单位为（mm）。会被 st_prep_buffer 修改

  float max_junction_speed_sqr; // 基于方向向量的连接入口速度限制，单位为（mm/min）^2。
  float rapid_rate;             // 根据块方向调整的最大速率，单位为（mm/min）。
  float programmed_rate;        // 此块的编程速率，单位为（mm/min）。
} plan_block_t;


// 传递给运动计划器的新运动数据
typedef struct {
  float feed_rate;          // 直线运动进给速率，在快速移动时该值被忽略.
  float spindle_speed;      // 表示通过直线运动希望达到的主轴转速
  uint8_t condition;        // 位标志来指示运动计划器的状态或条件
  #ifdef USE_LINE_NUMBERS
    int32_t line_number;    // 当前执行的行号
  #endif
} plan_line_data_t;

// Initialize and reset the motion plan subsystem
void plan_reset(); // Reset all
void plan_reset_buffer(); // Reset buffer only.

// Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position
// in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed
// rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes.
uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data);

// Called when the current block is no longer needed. Discards the block and makes the memory
// availible for new blocks.
void plan_discard_current_block();

// Gets the planner block for the special system motion cases. (Parking/Homing)
plan_block_t *plan_get_system_motion_block();

// Gets the current block. Returns NULL if buffer empty
plan_block_t *plan_get_current_block();

// Called periodically by step segment buffer. Mostly used internally by planner.
uint8_t plan_next_block_index(uint8_t block_index);

// Called by step segment buffer when computing executing block velocity profile.
float plan_get_exec_block_exit_speed_sqr();

// Called by main program during planner calculations and step segment buffer during initialization.
float plan_compute_profile_nominal_speed(plan_block_t *block);

// Re-calculates buffered motions profile parameters upon a motion-based override change.
void plan_update_velocity_profile_parameters();

// Reset the planner position vector (in steps)
void plan_sync_position();

// Reinitialize plan with a partially completed block
void plan_cycle_reinitialize();

// Returns the number of available blocks are in the planner buffer.
uint8_t plan_get_block_buffer_available();

// Returns the number of active blocks are in the planner buffer.
// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h
uint8_t plan_get_block_buffer_count();

// Returns the status of the block ring buffer. True, if buffer is full.
uint8_t plan_check_full_buffer();

void plan_get_planner_mpos(float *target);


#endif
